home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / fpc / compiler / pdecl.pas < prev    next >
Pascal/Delphi Source File  |  1998-09-24  |  67KB  |  1,778 lines

  1. {
  2.     $Id: pdecl.pas,v 1.1.1.1.2.2 1998/04/27 23:07:02 peter Exp $
  3.     Copyright (c) 1993-98 by Florian Klaempfl
  4.  
  5.     Does declaration parsing for Free Pascal
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  ****************************************************************************
  22. }
  23. unit pdecl;
  24.  
  25.   interface
  26.  
  27.     uses
  28.       globals,symtable;
  29.  
  30.     var
  31.        { pointer to the last read type symbol, (for "forward" }
  32.        { types)                                               }
  33.        lasttypesym : ptypesym;
  34.  
  35.        { hack, which allows to use the current parsed }
  36.        { object type as function argument type        }
  37.        testcurobject : byte;
  38.        curobjectname : stringid;
  39.  
  40.     { reads a string type with optional length }
  41.     { and returns a pointer to the string      }
  42.     { definition                               }
  43.     function stringtype : pdef;
  44.  
  45.     { reads a string, file type or a type id and returns a name and }
  46.     { pdef                                                          }
  47.     function single_type(var s : string) : pdef;
  48.  
  49.     { reads the declaration blocks }
  50.     procedure read_declarations(islibrary : boolean);
  51.  
  52.     { reads declarations in the interface part of a unit }
  53.     procedure read_interface_declarations;
  54.  
  55.   implementation
  56.  
  57.     uses
  58.        cobjects,scanner,aasm,tree,pass_1,
  59.        types,hcodegen,verbose,systems
  60. {$ifdef GDB}
  61.        ,gdb
  62. {$endif GDB}
  63.        { parser specific stuff }
  64.        ,pbase,ptconst,pexpr,psub,pexports
  65.        { processor specific stuff }
  66. {$ifdef i386}
  67.        ,i386
  68. {$endif}
  69. {$ifdef m68k}
  70.        ,m68k
  71. {$endif}
  72.        ;
  73.  
  74.     function read_type(const name : stringid) : pdef;forward;
  75.     procedure read_var_decs(is_record : boolean;do_absolute : boolean);forward;
  76.  
  77.     procedure const_dec;
  78.  
  79.       var
  80.          name : stringid;
  81.          p : ptree;
  82.          def : pdef;
  83.          ps : pconstset;
  84.          pd : pdouble;
  85.  
  86.       begin
  87.          consume(_CONST);
  88.          repeat
  89.            name:=pattern;
  90.            consume(ID);
  91.            case token of
  92.               EQUAL:
  93.             begin
  94.                    consume(EQUAL);
  95.                    p:=expr;
  96.                    do_firstpass(p);
  97.                    case p^.treetype of
  98.                       ordconstn:
  99.                         begin
  100.                            if is_constintnode(p) then
  101.                              symtablestack^.insert(new(pconstsym,init(name,constint,p^.value,nil)))
  102.                            else if is_constcharnode(p) then
  103.                              symtablestack^.insert(new(pconstsym,init(name,constchar,p^.value,nil)))
  104.                            else if is_constboolnode(p) then
  105.                              symtablestack^.insert(new(pconstsym,init(name,constbool,p^.value,nil)))
  106.                            else if p^.resulttype^.deftype=enumdef then
  107.                              symtablestack^.insert(new(pconstsym,init(name,constord,p^.value,p^.resulttype)))
  108.                            else internalerror(111);
  109.                         end;
  110.                       stringconstn:
  111.                         {values is disposed with p so I need a copy !}
  112.                         symtablestack^.insert(new(pconstsym,init(name,conststring,longint(stringdup(p^.values^)),nil)));
  113.                       realconstn : begin
  114.                                       new(pd);
  115.                                       pd^:=p^.valued;
  116.                                       symtablestack^.insert(new(pconstsym,init(name,constreal,longint(pd),nil)));
  117.                                    end;
  118.                       setconstrn : begin
  119.                                       new(ps);
  120.                                       ps^:=p^.constset^;
  121.                                       symtablestack^.insert(new(pconstsym,init(name,
  122.                                         constseta,longint(ps),p^.resulttype)));
  123.                                    end;
  124.                       else Message(cg_e_illegal_expression);
  125.                    end;
  126.                    consume(SEMICOLON);
  127.                 end;
  128.               COLON:
  129.             begin
  130.                    { this was missed, so const s : ^string = nil gives an
  131.                      error (FK)
  132.                    }
  133.                    parse_types:=true;
  134.                    consume(COLON);
  135.                    def:=read_type('');
  136.                    symtablestack^.insert(new(ptypedconstsym,init(name,def)));
  137.                    parse_types:=false;
  138.                    consume(EQUAL);
  139.                    readtypedconst(def);
  140.                    consume(SEMICOLON);
  141.                 end;
  142.               else consume(EQUAL);
  143.            end;
  144.          until token<>ID;
  145.       end;
  146.  
  147.     procedure label_dec;
  148.  
  149.       var
  150.          hl : plabel;
  151.  
  152.       begin
  153.          consume(_LABEL);
  154.          if not(cs_support_goto in aktswitches) then
  155.            Message(sym_e_goto_and_label_not_supported);
  156.          repeat
  157.            if not(token in [ID,INTCONST]) then
  158.              consume(ID)
  159.            else
  160.              begin
  161.                 getlabel(hl);
  162.                 symtablestack^.insert(new(plabelsym,init(pattern,hl)));
  163.                 consume(token);
  164.              end;
  165.            if token<>SEMICOLON then consume(COMMA);
  166.          until not(token in [ID,INTCONST]);
  167.          consume(SEMICOLON);
  168.       end;
  169.  
  170.     { reads a string type with optional length }
  171.     { and returns a pointer to the string      }
  172.     { definition                               }
  173.     function stringtype : pdef;
  174.  
  175.       var
  176.          p : ptree;
  177.          d : pdef;
  178.  
  179.       begin
  180.          consume(_STRING);
  181.          if token=LECKKLAMMER then
  182.            begin
  183.               consume(LECKKLAMMER);
  184.               p:=expr;
  185.               do_firstpass(p);
  186.               if not is_constintnode(p) then
  187.                 Message(cg_e_illegal_expression);
  188. {$ifndef UseLongString}
  189.               if (p^.value<1) or (p^.value>255) then
  190.                 begin
  191.                    Message(parser_e_string_too_long);
  192.                    p^.value:=255;
  193.                 end;
  194.               consume(RECKKLAMMER);
  195.               if p^.value<>255 then
  196.                 d:=new(pstringdef,init(p^.value))
  197. {$ifndef GDB}
  198.                  else d:=new(pstringdef,init(255));
  199. {$else * GDB *}
  200.                  else d:=globaldef('SYSTEM.STRING');
  201. {$endif * GDB *}
  202. {$else UseLongString}
  203.               if p^.value>255 then
  204.                 d:=new(pstringdef,longinit(p^.value)
  205.               else if p^.value<>255 then
  206.                 d:=new(pstringdef,init(p^.value))
  207. {$ifndef GDB}
  208.                  else d:=new(pstringdef,init(255));
  209. {$else * GDB *}
  210.                  else d:=globaldef('SYSTEM.STRING');
  211. {$endif * GDB *}
  212. {$endif UseLongString}
  213.               disposetree(p);
  214.            end
  215. {$ifndef GDB}
  216.                  else d:=new(pstringdef,init(255));
  217. {$else * GDB *}
  218.                  else d:=globaldef('SYSTEM.STRING');
  219. {$endif * GDB *}
  220.                  stringtype:=d;
  221.           end;
  222.  
  223.     { reads a type definition and returns a pointer }
  224.     { to a appropriating pdef, s gets the name of   }
  225.     { the type to allow name mangling               }
  226.     function id_type(var s : string) : pdef;
  227.  
  228.       begin
  229.          s:=pattern;
  230.          consume(ID);
  231.          if (testcurobject=2) and (curobjectname=pattern) then
  232.            begin
  233.               id_type:=aktobjectdef;
  234.               exit;
  235.            end;
  236.          getsym(s,true);
  237.          if assigned(srsym) then
  238.            begin
  239.                   if srsym^.typ=unitsym then
  240.                         begin
  241.                            consume(POINT);
  242.                            getsymonlyin(punitsym(srsym)^.unitsymtable,pattern);
  243.                            s:=pattern;
  244.                            consume(ID);
  245.                         end;
  246.                   if srsym^.typ<>typesym then
  247.                         begin
  248.                            Message(sym_e_type_id_expected);
  249.                            lasttypesym:=ptypesym(srsym);
  250.                            id_type:=generrordef;
  251.                            exit;
  252.                         end;
  253.            end;
  254.          lasttypesym:=ptypesym(srsym);
  255.          id_type:=ptypesym(srsym)^.definition;
  256.       end;
  257.  
  258.     { reads a string, file type or a type id and returns a name and }
  259.     { pdef                                                          }
  260.     function single_type(var s : string) : pdef;
  261.  
  262.        var
  263.           hs : string;
  264.  
  265.        begin
  266.           case token of
  267.             _STRING:
  268.                 begin
  269.                    single_type:=stringtype;
  270.                    s:='STRING';
  271.                    lasttypesym:=nil;
  272.                 end;
  273.             _FILE:
  274.                 begin
  275.                    consume(_FILE);
  276.                    if token=_OF then
  277.                      begin
  278.                         consume(_OF);
  279.                         single_type:=new(pfiledef,init(ft_typed,single_type(hs)));
  280.                         s:='FILE$OF$'+hs;
  281.                      end
  282.                    else
  283.                      begin
  284.                         { single_type:=new(pfiledef,init(ft_untyped,nil));}
  285.                         single_type:=cfiledef;
  286.                         s:='FILE';
  287.                      end;
  288.                    lasttypesym:=nil;
  289.                 end;
  290.             else single_type:=id_type(s);
  291.          end;
  292.       end;
  293.  
  294.     { this function parses an object or class declaration }
  295.     function object_dec(const n : stringid;fd : pobjectdef) : pdef;
  296.  
  297.       var
  298.          actmembertype : symprop;
  299.          there_is_a_destructor : boolean;
  300.          is_a_class : boolean;
  301.          childof : pobjectdef;
  302.          aktclass : pobjectdef;
  303.  
  304.       procedure constructor_head;
  305.  
  306.         begin
  307.            consume(_CONSTRUCTOR);
  308.            { must be at same level as in implementation }
  309.            _proc_head(poconstructor);
  310.  
  311.            if (cs_checkconsname in aktswitches) and (aktprocsym^.name<>'INIT') then
  312.             Message(parser_e_constructorname_must_be_init);
  313.  
  314.            consume(SEMICOLON);
  315.              begin
  316.                 if (aktclass^.options and oois_class)<>0 then
  317.                   begin
  318.                      { CLASS constructors return the created instance }
  319.                      aktprocsym^.definition^.retdef:=aktclass;
  320.                   end
  321.                 else
  322.                   begin
  323.                      { OBJECT constructors return a boolean }
  324. {$IfDef GDB}
  325.                      {GDB doesn't like unnamed types !}
  326.                      aktprocsym^.definition^.retdef:=
  327.                        globaldef('boolean');
  328. {$Else * GDB *}
  329.                      aktprocsym^.definition^.retdef:=
  330.                         new(porddef,init(bool8bit,0,1));
  331.  
  332. {$Endif * GDB *}
  333.                   end;
  334.              end;
  335.         end;
  336.  
  337.       procedure property_dec;
  338.  
  339.         var
  340.            sym : psym;
  341.            propertyparas : pdefcoll;
  342.  
  343.         { returns the matching procedure to access a property }
  344.         function get_procdef : pprocdef;
  345.  
  346.           var
  347.              p : pprocdef;
  348.  
  349.           begin
  350.              p:=pprocsym(sym)^.definition;
  351.              get_procdef:=nil;
  352.              while assigned(p) do
  353.                begin
  354.                   if equal_paras(p^.para1,propertyparas) then
  355.                     break;
  356.                   p:=p^.nextoverloaded;
  357.                end;
  358.              get_procdef:=p;
  359.           end;
  360.  
  361.         var
  362.            hp2,datacoll : pdefcoll;
  363.            p,p2 : ppropertysym;
  364.            overriden : psym;
  365.            hs : string;
  366.            code : word;
  367.            varspez : tvarspez;
  368.            sc : pstringcontainer;
  369.            hp : pdef;
  370.            s : string;
  371.  
  372.         begin
  373.            { check for a class }
  374.            if (aktclass^.options and oois_class=0) then
  375.             Message(parser_e_syntax_error);
  376.            consume(_PROPERTY);
  377.            if token=ID then
  378.              begin
  379.                 p:=new(ppropertysym,init(pattern));
  380.                 consume(ID);
  381.                 propertyparas:=nil;
  382.                 datacoll:=nil;
  383.                 { property parameters ? }
  384.                 if token=LECKKLAMMER then
  385.                   begin
  386.                      { create a list of the parameters in propertyparas }
  387.                      consume(LECKKLAMMER);
  388.                      inc(testcurobject);
  389.                      repeat
  390.                        if token=_VAR then
  391.                          begin
  392.                             consume(_VAR);
  393.                             varspez:=vs_var;
  394.                          end
  395.                        else if token=_CONST then
  396.                          begin
  397.                             consume(_CONST);
  398.                             varspez:=vs_const;
  399.                          end
  400.                        else varspez:=vs_value;
  401.                        sc:=idlist;
  402.                        if token=COLON then
  403.                          begin
  404.                             consume(COLON);
  405.                             if token=_ARRAY then
  406.                               begin
  407.                                  if (varspez<>vs_const) and
  408.                                    (varspez<>vs_var) then
  409.                                    begin
  410.                                       varspez:=vs_const;
  411.                                       Message(parser_e_illegal_open_parameter);
  412.                                    end;
  413.                                  consume(_ARRAY);
  414.                                  consume(_OF);
  415.                                  { define range and type of range }
  416.                                  hp:=new(parraydef,init(0,-1,s32bitdef));
  417.                                  { define field type }
  418.                                  parraydef(hp)^.definition:=single_type(s);
  419.                               end
  420.                             else
  421.                               hp:=single_type(s);
  422.                          end
  423.                        else
  424.                          hp:=new(pformaldef,init);
  425.                        s:=sc^.get;
  426.                        while s<>'' do
  427.                          begin
  428.                             new(hp2);
  429.                             hp2^.paratyp:=varspez;
  430.                             hp2^.data:=hp;
  431.                             hp2^.next:=propertyparas;
  432.                             propertyparas:=hp2;
  433.                             s:=sc^.get;
  434.                          end;
  435.                        dispose(sc,done);
  436.                        if token=SEMICOLON then consume(SEMICOLON)
  437.                      else break;
  438.                      until false;
  439.                      dec(testcurobject);
  440.                      consume(RECKKLAMMER);
  441.                   end;
  442.                 { overriden property ?                                       }
  443.                 { force property interface, if there is a property parameter }
  444.                 if (token=COLON) or assigned(propertyparas) then
  445.                   begin
  446.                      consume(COLON);
  447.                      p^.proptype:=single_type(hs);
  448.                      if (token=ID) and (pattern='INDEX') then
  449.                        begin
  450.                           consume(ID);
  451.                           p^.options:=p^.options or ppo_indexed;
  452.                           if token=INTCONST then
  453.                             val(pattern,p^.index,code);
  454.                           consume(INTCONST);
  455.                           { concat a longint to the para template }
  456.                           new(hp2);
  457.                           hp2^.paratyp:=vs_value;
  458.                           hp2^.data:=s32bitdef;
  459.                           hp2^.next:=propertyparas;
  460.                           propertyparas:=hp2;
  461.                        end;
  462.                   end
  463.                 else
  464.                   begin
  465.                      { do an property override }
  466.                      overriden:=search_class_member(aktclass,pattern);
  467.                      if assigned(overriden) and (overriden^.typ=propertysym) then
  468.                        begin
  469.                           { take the whole info: }
  470.                           p^.options:=ppropertysym(overriden)^.options;
  471.                           p^.index:=ppropertysym(overriden)^.index;
  472.                           p^.writeaccesssym:=ppropertysym(overriden)^.writeaccesssym;
  473.                           p^.readaccesssym:=ppropertysym(overriden)^.readaccesssym;
  474.                        end
  475.                      else
  476.                        begin
  477.                           p^.proptype:=generrordef;
  478.                           message(parser_e_no_property_found_to_override);
  479.                        end;
  480.                   end;
  481.                 if (token=ID) and (pattern='READ') then
  482.                   begin
  483.                      consume(ID);
  484.                      sym:=search_class_member(aktclass,pattern);
  485.                      if not(assigned(sym)) then
  486.                        Message1(sym_e_unknown_id,pattern)
  487.                      else
  488.                        begin
  489.                           { !!!! check sym }
  490.                           { varsym aren't allowed for an indexed property
  491.                             or an property with parameters }
  492.                           if ((sym^.typ=varsym) and
  493.                             (((p^.options and ppo_indexed)<>0) or
  494.                              assigned(propertyparas))) or
  495.                              not(sym^.typ in [varsym,procsym]) then
  496.                             Message(parser_e_ill_property_access_sym);
  497.                           { search the matching definition }
  498.                           if sym^.typ=procsym then
  499.                             begin
  500.                                { !!!!!! }
  501.                             end;
  502.                           p^.readaccesssym:=sym;
  503.                        end;
  504.                      consume(ID);
  505.                   end;
  506.                 if (token=ID) and (pattern='WRITE') then
  507.                   begin
  508.                      consume(ID);
  509.                      sym:=search_class_member(aktclass,pattern);
  510.                      if not(assigned(sym)) then
  511.                        Message1(sym_e_unknown_id,pattern)
  512.                      else
  513.                        begin
  514.                           { !!!! check sym }
  515.                           if ((sym^.typ=varsym) and
  516.                             (((p^.options and ppo_indexed)<>0)
  517.                             { or property paras })) or
  518.                              not(sym^.typ in [varsym,procsym]) then
  519.                             Message(parser_e_ill_property_access_sym);
  520.                           { search the matching definition }
  521.                           if sym^.typ=procsym then
  522.                             begin
  523.                                { !!!!!! }
  524.                             end;
  525.                           p^.writeaccesssym:=sym;
  526.                        end;
  527.                      consume(ID);
  528.                   end;
  529.                 if (token=ID) and (pattern='STORED') then
  530.                   begin
  531.                      consume(ID);
  532.                      { !!!!!!!! }
  533.                   end;
  534.                 if (token=ID) and (pattern='DEFAULT') then
  535.                   begin
  536.                      consume(ID);
  537.                      if token=SEMICOLON then
  538.                        begin
  539.                           p2:=search_default_property(aktclass);
  540.                           if assigned(p2) then
  541.                             message1(parser_e_only_one_default_property,
  542.                               pobjectdef(p2^.owner^.defowner)^.name^)
  543.                           else
  544.                             begin
  545.                                p^.options:=p^.options and ppo_defaultproperty;
  546.                                if not(assigned(propertyparas)) then
  547.                                  message(parser_e_property_need_paras);
  548.                             end;
  549.                        end
  550.                      else
  551.                        begin
  552.                           { !!!!!!! storage }
  553.                        end;
  554.                      consume(SEMICOLON);
  555.                   end
  556.                 else if (token=ID) and (pattern='NODEFAULT') then
  557.                   begin
  558.                      consume(ID);
  559.                      { !!!!!!!! }
  560.                   end;
  561.                 symtablestack^.insert(p);
  562.                 { clean up }
  563.                 if assigned(datacoll) then
  564.                   dispose(datacoll);
  565.              end
  566.            else
  567.               consume(ID);
  568.            consume(SEMICOLON);
  569.         end;
  570.  
  571.       procedure destructor_head;
  572.  
  573.         begin
  574.            consume(_DESTRUCTOR);
  575.            _proc_head(podestructor);
  576.            if (cs_checkconsname in aktswitches) and (aktprocsym^.name<>'DONE') then
  577.             Message(parser_e_destructorname_must_be_done);
  578.            consume(SEMICOLON);
  579.            if assigned(aktprocsym^.definition^.para1) then
  580.             Message(parser_e_no_paras_for_destructor);
  581.            { no return value }
  582.            aktprocsym^.definition^.retdef:=voiddef;
  583.         end;
  584.  
  585.       procedure object_komponenten;
  586.  
  587.         var
  588.            oldparse_only : boolean;
  589.  
  590.         begin
  591.            repeat
  592.              case token of
  593.                 ID:
  594.                   begin
  595.                      if (pattern='PUBLIC') or
  596.                        (pattern='PUBLISHED') or
  597.                        (pattern='PROTECTED') or
  598.                        (pattern='PRIVATE') then
  599.                        exit;
  600.                      read_var_decs(false,false);
  601.                   end;
  602.                 _PROPERTY:
  603.                   property_dec;
  604.                 _PROCEDURE,_FUNCTION,_CLASS:
  605.                   begin
  606.                      oldparse_only:=parse_only;
  607.                      parse_only:=true;
  608.                      proc_head;
  609.                      parse_only:=oldparse_only;
  610.                      if (token=ID) and
  611.                        ((pattern='VIRTUAL') or (pattern='DYNAMIC')) then
  612.                        begin
  613.                           if actmembertype=sp_private then
  614.                            Message(parser_w_priv_meth_not_virtual);
  615.                           consume(ID);
  616.                           consume(SEMICOLON);
  617.                           aktprocsym^.definition^.options:=
  618.                             aktprocsym^.definition^.options or povirtualmethod;
  619.                           aktclass^.options:=aktclass^.options or oo_hasvirtual;
  620.                        end
  621.                      else if (token=ID) and (pattern='OVERRIDE') then
  622.                        begin
  623.                           consume(ID);
  624.                           consume(SEMICOLON);
  625.                           aktprocsym^.definition^.options:=
  626.                             aktprocsym^.definition^.options or pooverridingmethod or povirtualmethod;
  627.                        end;
  628.                      { Delphi II extension }
  629.                      if (token=ID) and (pattern='ABSTRACT') then
  630.                        begin
  631.                           consume(ID);
  632.                           consume(SEMICOLON);
  633.                           if (aktprocsym^.definition^.options and povirtualmethod)<>0 then
  634.                             begin
  635.                                aktprocsym^.definition^.options:=
  636.                                 aktprocsym^.definition^.options or
  637.                                   poabstractmethod;
  638.                             end
  639.                           else
  640.                             Message(parser_e_only_virtual_methods_abstract);
  641.                           { the method is defined }
  642.                           aktprocsym^.definition^.forwarddef:=false;
  643.                        end;
  644.                      if (token=ID) and (pattern='STATIC') and
  645.                         (cs_static_keyword in aktswitches) then
  646.                        begin
  647.                           consume(ID);
  648.                           consume(SEMICOLON);
  649.                           aktprocsym^.properties:=
  650.                             aktprocsym^.properties or
  651.                               sp_static;
  652.                           aktprocsym^.definition^.options:=
  653.                             aktprocsym^.definition^.options or
  654.                                postaticmethod;
  655.                        end;
  656.                   end;
  657.                 _CONSTRUCTOR:
  658.                   begin
  659.                      if actmembertype<>sp_public then
  660.                        Message(parser_e_constructor_cannot_be_private);
  661.                      oldparse_only:=parse_only;
  662.                      parse_only:=true;
  663.                      constructor_head;
  664.                      parse_only:=oldparse_only;
  665.                      if (token=ID) and
  666.                        ((pattern='VIRTUAL') or (pattern='DYNAMIC')) then
  667.                        Message(parser_e_constructor_cannot_be_not_virtual);
  668.                   end;
  669.                 _DESTRUCTOR:
  670.                   begin
  671.                      if there_is_a_destructor then
  672.                       Message(parser_n_only_one_destructor);
  673.                      there_is_a_destructor:=true;
  674.  
  675.                      if actmembertype<>sp_public then
  676.                       Message(parser_e_destructor_cannot_be_private);
  677.                      oldparse_only:=parse_only;
  678.                      parse_only:=true;
  679.                      destructor_head;
  680.                      parse_only:=oldparse_only;
  681.                      if (token=ID) and
  682.                        ((pattern='VIRTUAL') or (pattern='DYNAMIC')) then
  683.                        begin
  684.                           consume(ID);
  685.                           consume(SEMICOLON);
  686.                           aktprocsym^.definition^.options:=
  687.                             aktprocsym^.definition^.options or povirtualmethod;
  688.                        end
  689.                      else if (token=ID) and (pattern='OVERRIDE') then
  690.                        begin
  691.                           consume(ID);
  692.                           consume(SEMICOLON);
  693.                           aktprocsym^.definition^.options:=
  694.                             aktprocsym^.definition^.options or pooverridingmethod or povirtualmethod;
  695.                        end;
  696.                   end;
  697.                 _END : exit;
  698.                 else Message(parser_e_syntax_error);
  699.              end;
  700.            until false;
  701.         end;
  702.  
  703.       var
  704.          hs : string;
  705.          pcrd : pclassrefdef;
  706.          hp1 : pdef;
  707.          oldprocsym:Pprocsym;
  708.  
  709.       begin
  710.          {Nowadays aktprocsym may already have a value, so we need to save
  711.           it.}
  712.          oldprocsym:=aktprocsym;
  713.          { forward is resolved }
  714.          if assigned(fd) then
  715.            fd^.options:=fd^.options and not(oo_isforward);
  716.  
  717.          there_is_a_destructor:=false;
  718.          actmembertype:=sp_public;
  719.  
  720.          { objects and class types can't be declared local }
  721.          if (symtablestack^.symtabletype<>globalsymtable) and
  722.            (symtablestack^.symtabletype<>staticsymtable) then
  723.            Message(parser_e_no_local_objects);
  724.  
  725.          { distinguish classes and objects }
  726.          if token=_OBJECT then
  727.            begin
  728.               is_a_class:=false;
  729.               consume(_OBJECT)
  730.            end
  731.          else
  732.            begin
  733.               is_a_class:=true;
  734.               consume(_CLASS);
  735.               if not(assigned(fd)) and (token=_OF) then
  736.                 begin
  737.                    { a hack, but it's easy to handle }
  738.                    { class reference type }
  739.                    consume(_OF);
  740.                    if typecanbeforward then
  741.                      forwardsallowed:=true;
  742.                    hp1:=single_type(hs);
  743.  
  744.                    { accept hp1, if is a forward def ...}
  745.                    if ((lasttypesym<>nil)
  746.                        and ((lasttypesym^.properties and sp_forwarddef)<>0)) or
  747.                    { or a class
  748.                      (if the foward defined type is a class is checked, when
  749.                       the forward is resolved)
  750.                    }
  751.                      ((hp1^.deftype=objectdef) and (
  752.                      (pobjectdef(hp1)^.options and oois_class)<>0)) then
  753.                      begin
  754.                         pcrd:=new(pclassrefdef,init(hp1));
  755.                     object_dec:=pcrd;
  756.                         {I add big troubles here
  757.                         with var p : ^byte in graph.putimage
  758.                         because a save_forward was called and
  759.                         no resolve forward
  760.                         => so the definition was rewritten after
  761.                         having been disposed !!
  762.                         Strange problems appeared !!!!}
  763.                         {Anyhow forwards should only be allowed
  764.                         inside a type statement ??
  765.                         don't you think so }
  766.                         if (lasttypesym<>nil)
  767.                           and ((lasttypesym^.properties and sp_forwarddef)<>0) then
  768.                             lasttypesym^.forwardpointer:=ppointerdef(pcrd);
  769.                         forwardsallowed:=false;
  770.                      end
  771.                    else
  772.                      begin
  773.                         Message(parser_e_class_type_expected);
  774.                         object_dec:=new(perrordef,init);
  775.                      end;
  776.                    exit;
  777.                 end
  778.               { forward class }
  779.               else if not(assigned(fd)) and (token=SEMICOLON) then
  780.                 begin
  781.                    { also anonym objects aren't allow (o : object a : longint; end;) }
  782.                    if n='' then
  783.                     Message(parser_e_no_anonym_objects);
  784.                    if n='TOBJECT' then
  785.                      begin
  786.                         aktclass:=new(pobjectdef,init(n,nil));
  787.                         class_tobject:=aktclass;
  788.                      end
  789.                    else
  790.                      aktclass:=new(pobjectdef,init(n,class_tobject));
  791.                    aktclass^.options:=aktclass^.options or oois_class or oo_isforward;
  792.                    object_dec:=aktclass;
  793.                    exit;
  794.                 end;
  795.            end;
  796.  
  797.          { also anonym objects aren't allow (o : object a : longint; end;) }
  798.          if n='' then
  799.            Message(parser_e_no_anonym_objects);
  800.  
  801.          { read the parent class }
  802.          if token=LKLAMMER then
  803.            begin
  804.               consume(LKLAMMER);
  805.               { does not allow objects.tobject !! }
  806.               {if token<>ID then
  807.                 consume(ID);
  808.               getsym(pattern,true);}
  809.               childof:=pobjectdef(id_type(pattern));
  810.               if (childof^.deftype<>objectdef) then
  811.                  begin
  812.                     Message(parser_e_class_type_expected);
  813.                     childof:=nil;
  814.                  end;
  815.                    { a mix of class and object isn't allowed }
  816.               if (((childof^.options and oois_class)<>0) and not is_a_class) or
  817.                  (((childof^.options and oois_class)=0) and is_a_class) then
  818.                 Message(parser_e_mix_of_classes_and_objects);
  819.               consume(RKLAMMER);
  820.               if assigned(fd) then
  821.                 begin
  822.                    fd^.childof:=childof;
  823.                    aktclass:=fd;
  824.                 end
  825.               else
  826.                 aktclass:=new(pobjectdef,init(n,childof));
  827.            end
  828.          { if no parent class, then a class get tobject as parent }
  829.          else if is_a_class then
  830.            begin
  831.               { is the current class tobject?        }
  832.               { so you could define your own tobject }
  833.               if n='TOBJECT' then
  834.                 begin
  835.                    if assigned(fd) then
  836.                      aktclass:=fd
  837.                    else
  838.                      aktclass:=new(pobjectdef,init(n,nil));
  839.                    class_tobject:=aktclass;
  840.                 end
  841.               else
  842.                 begin
  843.                    childof:=class_tobject;
  844.                    if assigned(fd) then
  845.                      begin
  846.                         aktclass:=fd;
  847.                         aktclass^.childof:=childof;
  848.                      end
  849.                    else
  850.                      aktclass:=new(pobjectdef,init(n,childof));
  851.                 end;
  852.            end
  853.          else aktclass:=new(pobjectdef,init(n,nil));
  854.  
  855.          { set the class attribute }
  856.          if is_a_class then
  857.            aktclass^.options:=aktclass^.options or oois_class;
  858.  
  859.  
  860.          aktobjectdef:=aktclass;
  861.  
  862.          { default access is public }
  863.          actmembertype:=sp_public;
  864.          aktclass^.publicsyms^.next:=symtablestack;
  865.          symtablestack:=aktclass^.publicsyms;
  866.          procinfo._class:=aktclass;
  867.          testcurobject:=1;
  868.          curobjectname:=n;
  869.          while token<>_END do
  870.            begin
  871.               if (token=ID) and (pattern='PRIVATE') then
  872.                 begin
  873.                    consume(ID);
  874.                    actmembertype:=sp_private;
  875.                    current_object_option:=sp_private;
  876.                 end;
  877.               if (token=ID) and (pattern='PROTECTED') then
  878.                 begin
  879.                    consume(ID);
  880.                    current_object_option:=sp_protected;
  881.                    actmembertype:=sp_protected;
  882.                 end;
  883.               if (token=ID) and (pattern='PUBLIC') then
  884.                 begin
  885.                    consume(ID);
  886.                    current_object_option:=sp_public;
  887.                    actmembertype:=sp_public;
  888.                 end;
  889.               if (token=ID) and (pattern='PUBLISHED') then
  890.                 begin
  891.                    consume(ID);
  892.                    current_object_option:=sp_public;
  893.                    actmembertype:=sp_public;
  894.                 end;
  895.               object_komponenten;
  896.            end;
  897.          current_object_option:=sp_public;
  898.          consume(_END);
  899.          testcurobject:=0;
  900.          curobjectname:='';
  901.  
  902. {$ifdef MAKELIB}
  903.         datasegment^.concat(new(pai_cut,init));
  904. {$endif MAKELIB}
  905. {$ifdef GDB}
  906.          { generate the VMT }
  907.          if cs_debuginfo in aktswitches then
  908.            begin
  909.               do_count_dbx:=true;
  910.               if assigned(aktclass^.owner) and assigned(aktclass^.owner^.name) then
  911.                debuglist^.concat(new(pai_stabs,init(strpnew('"vmt_'+aktclass^.owner^.name^+n+':S'+
  912.                 typeglobalnumber('__vtbl_ptr_type')+'",'+tostr(N_STSYM)+',0,0,'+aktclass^.vmt_mangledname))));
  913.            end;
  914. {$endif * GDB *}
  915.          datasegment^.concat(new(pai_symbol,init_global(aktclass^.vmt_mangledname)));
  916.  
  917.          { determine the size with publicsyms^.datasize, because }
  918.          { size gives back 4 for CLASSes                         }
  919.          datasegment^.concat(new(pai_const,init_32bit(aktclass^.publicsyms^.datasize)));
  920.          datasegment^.concat(new(pai_const,init_32bit(-aktclass^.publicsyms^.datasize)));
  921.  
  922.          { write pointer to parent VMT, this isn't implemented in TP }
  923.          { but this is not used in FPC ? (PM) }
  924.          { it's not used yet, but the delphi-operators as and is need it (FK) }
  925.          if assigned(aktclass^.childof) then
  926.            begin
  927.               datasegment^.concat(new(pai_const,init_symbol(strpnew(aktclass^.childof^.vmt_mangledname))));
  928.               if aktclass^.childof^.owner^.symtabletype=unitsymtable then
  929.                 concat_external(aktclass^.childof^.vmt_mangledname,EXT_NEAR);
  930.            end
  931.          else
  932.            datasegment^.concat(new(pai_const,init_32bit(0)));
  933.  
  934.          { this generates the entries }
  935.          genvmt(aktclass);
  936.  
  937.          { restore old state }
  938.          symtablestack:=symtablestack^.next;
  939.          procinfo._class:=nil;
  940.          {Restore the aktprocsym.}
  941.          aktprocsym:=oldprocsym;
  942.  
  943.          object_dec:=aktclass;
  944.       end;
  945.  
  946.     { reads a record declaration }
  947.     function record_dec : pdef;
  948.  
  949.       var
  950.          symtable : psymtable;
  951.  
  952.       begin
  953.          symtable:=new(psymtable,init(recordsymtable));
  954.          symtable^.next:=symtablestack;
  955.          symtablestack:=symtable;
  956.          consume(_RECORD);
  957.          read_var_decs(true,false);
  958.  
  959.          { may be scale record size to a size of n*4 ? }
  960.          if ((symtablestack^.datasize mod aktpackrecords)<>0) then
  961.            inc(symtablestack^.datasize,aktpackrecords-(symtablestack^.datasize mod aktpackrecords));
  962.  
  963.          consume(_END);
  964.          symtablestack:=symtable^.next;
  965.          record_dec:=new(precdef,init(symtable));
  966.       end;
  967.  
  968.     { reads a type definition and returns a pointer to it }
  969.     function read_type(const name : stringid) : pdef;
  970.  
  971.     function handle_procvar:Pprocvardef;
  972.  
  973.     var
  974.        sc : pstringcontainer;
  975.        s : string;
  976.        p : pdef;
  977.        varspez : tvarspez;
  978.        procvardef : pprocvardef;
  979.  
  980.     begin
  981.        procvardef:=new(pprocvardef,init);
  982.        if token=LKLAMMER then
  983.          begin
  984.             consume(LKLAMMER);
  985.             inc(testcurobject);
  986.             repeat
  987.               if token=_VAR then
  988.                 begin
  989.                    consume(_VAR);
  990.                    varspez:=vs_var;
  991.                 end
  992.               else if token=_CONST then
  993.                 begin
  994.                    consume(_CONST);
  995.                    varspez:=vs_const;
  996.                 end
  997.               else varspez:=vs_value;
  998.               sc:=idlist;
  999.               if token=COLON then
  1000.                 begin
  1001.                    consume(COLON);
  1002.                    if token=_ARRAY then
  1003.                      begin
  1004.                         if (varspez<>vs_const) and
  1005.                           (varspez<>vs_var) then
  1006.                           begin
  1007.                              varspez:=vs_const;
  1008.                              Message(parser_e_illegal_open_parameter);
  1009.                           end;
  1010.                         consume(_ARRAY);
  1011.                         consume(_OF);
  1012.                         { define range and type of range }
  1013.                         p:=new(parraydef,init(0,-1,s32bitdef));
  1014.                         { define field type }
  1015.                         parraydef(p)^.definition:=single_type(s);
  1016.                      end
  1017.                    else
  1018.                      p:=single_type(s);
  1019.                 end
  1020.               else
  1021.                 p:=new(pformaldef,init);
  1022.               s:=sc^.get;
  1023.               while s<>'' do
  1024.                 begin
  1025.                    procvardef^.concatdef(p,varspez);
  1026.                    s:=sc^.get;
  1027.                 end;
  1028.               dispose(sc,done);
  1029.               if token=SEMICOLON then consume(SEMICOLON)
  1030.             else break;
  1031.             until false;
  1032.             dec(testcurobject);
  1033.             consume(RKLAMMER);
  1034.          end;
  1035.        handle_procvar:=procvardef;
  1036.     end;
  1037.  
  1038.       var
  1039.          hp1,p : pdef;
  1040.          pt : ptree;
  1041.          aufdef : penumdef;
  1042.          aufsym : penumsym;
  1043.          ap : parraydef;
  1044.          s : stringid;
  1045.          l,v,oldaktpackrecords : longint;
  1046.          hs : string;
  1047.  
  1048.       procedure range_type;
  1049.  
  1050.         begin
  1051.            { it can be only a range type }
  1052.            pt:=expr;
  1053.            do_firstpass(pt);
  1054.  
  1055.            { valid expression ? }
  1056.            if (pt^.treetype<>rangen) or
  1057.               (pt^.left^.treetype<>ordconstn) then
  1058.              Begin
  1059.                Message(sym_e_error_in_type_def);
  1060.                { Here we create a node type with a range of 0  }
  1061.                { To make sure that no crashes will occur later }
  1062.                { on in the compiler.                           }
  1063.                p:=new(porddef,init(uauto,0,0));
  1064.              end
  1065.            else
  1066.              p:=new(porddef,init(uauto,pt^.left^.value,pt^.right^.value));
  1067.            disposetree(pt);
  1068.         end;
  1069.  
  1070.       begin
  1071.          case token of
  1072.             ID,_STRING,_FILE:
  1073.               p:=single_type(hs);
  1074.             LKLAMMER:
  1075.               begin
  1076.                  consume(LKLAMMER);
  1077.                  l:=-1;
  1078.                  aufsym := Nil;
  1079.                  aufdef:=new(penumdef,init);
  1080.                  repeat
  1081.                    s:=pattern;
  1082.                    consume(ID);
  1083.                    if token=ASSIGNMENT then
  1084.                      begin
  1085.                         consume(ASSIGNMENT);
  1086.                         v:=get_intconst;
  1087.                         { please leave that a note, allows type save }
  1088.                         { declarations in the win32 units !          }
  1089.                         if v<=l then
  1090.                          Message(parser_n_duplicate_enum);
  1091.                         l:=v;
  1092.                      end
  1093.                    else
  1094.                      inc(l);
  1095.                    constsymtable^.insert(new(penumsym,init(s,aufdef,l)));
  1096.                    if token=COMMA then
  1097.                      consume(COMMA)
  1098.                    else
  1099.                      break;
  1100.                  until false;
  1101.                  aufdef^.max:=l;
  1102.                  p:=aufdef;
  1103.                  consume(RKLAMMER);
  1104.               end;
  1105.             _ARRAY:
  1106.               begin
  1107.                  consume(_ARRAY);
  1108.                  consume(LECKKLAMMER);
  1109.                  p:=nil;
  1110.                  repeat
  1111.                    { read the expression and check it }
  1112.                    pt:=expr;
  1113.                    if pt^.treetype=typen then
  1114.                      begin
  1115.                         if pt^.resulttype^.deftype=enumdef then
  1116.                           begin
  1117.                              if p=nil then
  1118.                                begin
  1119.                                   ap:=new(parraydef,
  1120.                                     init(0,penumdef(pt^.resulttype)^.max,pt^.resulttype));
  1121.                                   p:=ap;
  1122.                                end
  1123.                              else
  1124.                                begin
  1125.                                   ap^.definition:=new(parraydef,
  1126.                                     init(0,penumdef(pt^.resulttype)^.max,pt^.resulttype));
  1127.                                   ap:=parraydef(ap^.definition);
  1128.                                end;
  1129.                           end
  1130.                         else if pt^.resulttype^.deftype=orddef then
  1131.                           begin
  1132.                              case porddef(pt^.resulttype)^.typ of
  1133.                                 s8bit,u8bit,s16bit,u16bit,s32bit :
  1134.                                   begin
  1135.                                      if p=nil then
  1136.                                        begin
  1137.                                           ap:=new(parraydef,init(porddef(pt^.resulttype)^.von,
  1138.                                             porddef(pt^.resulttype)^.bis,pt^.resulttype));
  1139.                                           p:=ap;
  1140.                                        end
  1141.                                      else
  1142.                                        begin
  1143.                                           ap^.definition:=new(parraydef,init(porddef(pt^.resulttype)^.von,
  1144.                                             porddef(pt^.resulttype)^.bis,pt^.resulttype));
  1145.                                           ap:=parraydef(ap^.definition);
  1146.                                        end;
  1147.                                   end;
  1148.                                 bool8bit:
  1149.                                   begin
  1150.                                      if p=nil then
  1151.                                        begin
  1152.                                           ap:=new(parraydef,init(0,1,pt^.resulttype));
  1153.                                           p:=ap;
  1154.                                        end
  1155.                                      else
  1156.                                        begin
  1157.                                           ap^.definition:=new(parraydef,init(0,1,pt^.resulttype));
  1158.                                           ap:=parraydef(ap^.definition);
  1159.                                        end;
  1160.                                   end;
  1161.                                 uchar:
  1162.                                   begin
  1163.                                            if p=nil then
  1164.                                                                                              begin
  1165.                                                 ap:=new(parraydef,init(0,255,pt^.resulttype));
  1166.                                                                                                     p:=ap;
  1167.                                              end
  1168.                                            else
  1169.                                              begin
  1170.                                                 ap^.definition:=new(parraydef,init(0,255,pt^.resulttype));
  1171.                                                 ap:=parraydef(ap^.definition);
  1172.                                              end;
  1173.                                                                                     end;
  1174.                                 else Message(sym_e_error_in_type_def);
  1175.                              end;
  1176.                           end
  1177.                         else Message(sym_e_error_in_type_def);
  1178.                      end
  1179.                    else
  1180.                      begin
  1181.                         do_firstpass(pt);
  1182.  
  1183.                         if (pt^.treetype<>rangen) or
  1184.                            (pt^.left^.treetype<>ordconstn) then
  1185.                           Message(sym_e_error_in_type_def);
  1186.                         { Registrierung der Grenzen erzwingen: }
  1187.                         {$IfNdef GDB}
  1188.                         if pt^.right^.resulttype=pdef(s32bitdef) then
  1189.                           pt^.right^.resulttype:=new(porddef,init(
  1190.                             s32bit,$80000000,$7fffffff));
  1191.                         {$EndIf GDB}
  1192.                         if p=nil then
  1193.                           begin
  1194.                              ap:=new(parraydef,init(pt^.left^.value,pt^.right^.value,pt^.right^.resulttype));
  1195.                              p:=ap;
  1196.                           end
  1197.                         else
  1198.                           begin
  1199.                              ap^.definition:=new(parraydef,init(pt^.left^.value,pt^.right^.value,pt^.right^.resulttype));
  1200.                              ap:=parraydef(ap^.definition);
  1201.                           end;
  1202.                      end;
  1203.                    disposetree(pt);
  1204.  
  1205.                    if token=COMMA then consume(COMMA)
  1206.                      else break;
  1207.                  until false;
  1208.                  consume(RECKKLAMMER);
  1209.                  consume(_OF);
  1210.                  hp1:=read_type('');
  1211.                  { if no error, set element type }
  1212.                  if assigned(ap) then
  1213.                    ap^.definition:=hp1;
  1214.                   end;
  1215.             _SET:
  1216.               begin
  1217.                  consume(_SET);
  1218.                  consume(_OF);
  1219.                  hp1:=read_type('');
  1220.                  case hp1^.deftype of
  1221.                     enumdef : p:=new(psetdef,init(hp1,penumdef(hp1)^.max));
  1222.                     orddef : begin
  1223.                                   case porddef(hp1)^.typ of
  1224.                                      uchar : p:=new(psetdef,init(hp1,255));
  1225.                                      u8bit,s8bit,u16bit,s16bit,s32bit :
  1226.                                        begin
  1227.                                           if (porddef(hp1)^.von>=0) then
  1228.                                             p:=new(psetdef,init(hp1,porddef(hp1)^.bis))
  1229.                                           else Message(sym_e_ill_type_decl_set);
  1230.                                        end;
  1231.                                   else Message(sym_e_ill_type_decl_set);
  1232.                                   end;
  1233.                                end;
  1234.                     else Message(sym_e_ill_type_decl_set);
  1235.                  end;
  1236.               end;
  1237.             CARET:
  1238.               begin
  1239.                  consume(CARET);
  1240.                  { forwards allowed only inside TYPE statements }
  1241.                  if typecanbeforward then
  1242.                     forwardsallowed:=true;
  1243.                  hp1:=single_type(hs);
  1244.                  p:=new(ppointerdef,init(hp1));
  1245. {$ifndef GDB}
  1246.                  if lasttypesym<>nil then
  1247.                    save_forward(ppointerdef(p),lasttypesym);
  1248. {$else * GDB *}
  1249.                  {I add big troubles here
  1250.                  with var p : ^byte in graph.putimage
  1251.                  because a save_forward was called and
  1252.                  no resolve forward
  1253.                  => so the definition was rewritten after
  1254.                  having been disposed !!
  1255.                  Strange problems appeared !!!!}
  1256.                  {Anyhow forwards should only be allowed
  1257.                  inside a type statement ??
  1258.                  don't you think so }
  1259.                  if (lasttypesym<>nil)
  1260.                    and ((lasttypesym^.properties and sp_forwarddef)<>0) then
  1261.                      lasttypesym^.forwardpointer:=ppointerdef(p);
  1262. {$endif * GDB *}
  1263.                  forwardsallowed:=false;
  1264.               end;
  1265.             _RECORD:
  1266.               p:=record_dec;
  1267.             _PACKED:
  1268.               begin
  1269.                  consume(_PACKED);
  1270.                  oldaktpackrecords:=aktpackrecords;
  1271.                  aktpackrecords:=1;
  1272.                  p:=record_dec;
  1273.                  aktpackrecords:=oldaktpackrecords;
  1274.               end;
  1275.             _CLASS,
  1276.             _OBJECT:
  1277.               p:=object_dec(name,nil);
  1278.             _PROCEDURE:
  1279.               begin
  1280.                  consume(_PROCEDURE);
  1281.                  p:=handle_procvar;
  1282.               end;
  1283.             _FUNCTION:
  1284.               begin
  1285.                  consume(_FUNCTION);
  1286.                  p:=handle_procvar;
  1287.                  consume(COLON);
  1288.                  pprocvardef(p)^.retdef:=single_type(hs);
  1289.               end;
  1290.             else
  1291.               range_type;
  1292.          end;
  1293.          read_type:=p;
  1294.       end;
  1295.  
  1296.     { search in symtablestack used, but not defined type }
  1297.     procedure testforward_types(p : psym);{$ifndef FPC}far;{$endif}
  1298.  
  1299.       begin
  1300.          if (p^.typ=typesym) and ((p^.properties and sp_forwarddef)<>0) then
  1301.            Message(sym_e_type_id_not_defined);
  1302.       end;
  1303.  
  1304.     { reads a type declaration to the symbol table }
  1305.     procedure type_dec;
  1306.  
  1307.       var
  1308.          typename : stringid;
  1309. {$ifdef dummy}
  1310.          olddef,newdef : pdef;
  1311.          s : string;
  1312. {$endif dummy}
  1313.  
  1314.       begin
  1315.          parse_types:=true;
  1316.          consume(_TYPE);
  1317.          typecanbeforward:=true;
  1318.          repeat
  1319.            typename:=pattern;
  1320.            consume(ID);
  1321.            consume(EQUAL);
  1322.              { here you loose the strictness of pascal
  1323.              for which a redefinition like
  1324.                childtype = parenttype;
  1325.                            child2type = parenttype;
  1326.              does not make the two child types equal !!
  1327.              here all vars from childtype and child2type
  1328.              get the definition of parenttype !!            }
  1329. {$ifdef testequaltype}
  1330.            if (token = ID) or (token=_FILE) or (token=_STRING) then
  1331.              begin
  1332.                 olddef := single_type(s);
  1333.                 { make a clone of olddef }
  1334.                 { is that ok ??? }
  1335.                 getmem(newdef,SizeOf(olddef));
  1336.                 move(olddef^,newdef^,SizeOf(olddef));
  1337.                 symtablestack^.insert(new(ptypesym,init(typename,newdef)));
  1338.              end
  1339.            else
  1340. {$endif testequaltype}
  1341.              begin
  1342.                 getsym(typename,false);
  1343.                 { check if it is the definition of a forward defined class }
  1344.                 if assigned(srsym) and (token=_CLASS) and
  1345.                   (srsym^.typ=typesym) and
  1346.                   (ptypesym(srsym)^.definition^.deftype=objectdef) and
  1347.                   ((pobjectdef(ptypesym(srsym)^.definition)^.options and oo_isforward)<>0) and
  1348.                   ((pobjectdef(ptypesym(srsym)^.definition)^.options and oois_class)<>0) then
  1349.                   begin
  1350.                      { we can ignore the result   }
  1351.                      { the definition is modified }
  1352.                      object_dec(typename,pobjectdef(ptypesym(srsym)^.definition));
  1353.                   end
  1354.                 else
  1355.                   symtablestack^.insert(new(ptypesym,init(typename,read_type(typename))));
  1356.              end;
  1357.            consume(SEMICOLON);
  1358.          until token<>ID;
  1359.          typecanbeforward:=false;
  1360. {$ifdef tp}
  1361.          symtablestack^.foreach(testforward_types);
  1362. {$else}
  1363.          symtablestack^.foreach(@testforward_types);
  1364. {$endif}
  1365.          resolve_forwards;
  1366.          parse_types:=false;
  1367.       end;
  1368.  
  1369.     { parses varaible declarations and inserts them in }
  1370.     { the top symbol table of symtablestack            }
  1371.     procedure var_dec;
  1372.  
  1373.       {var
  1374.          p : pdef;
  1375.          sc : pstringcontainer;      }
  1376.  
  1377.       begin
  1378.          consume(_VAR);
  1379.          read_var_decs(false,true);
  1380.       end;
  1381.  
  1382.     { reads the filed of a record into a        }
  1383.     { symtablestack, if record=false            }
  1384.     { variants are forbidden, so this procedure }
  1385.     { can be used to read object fields         }
  1386.     { if absolute is true, ABSOLUTE and file    }
  1387.     { types are allowed                         }
  1388.     { => the procedure is also used to read     }
  1389.     { a sequence of variable declaration        }
  1390.     procedure read_var_decs(is_record : boolean;do_absolute : boolean);
  1391.  
  1392.       var
  1393.          sc : pstringcontainer;
  1394.          s : stringid;
  1395.          l    : longint;
  1396.          code : word;
  1397.          hs : string;
  1398.          p,casedef : pdef;
  1399.          { maxsize contains the max. size of a variant }
  1400.          { startvarrec contains the start of the variant part of a record }
  1401.          maxsize,startvarrec : longint;
  1402.          pt : ptree;
  1403.          old_parse_types : boolean;
  1404.          { to handle absolute }
  1405.          abssym : pabsolutesym;
  1406.  
  1407.       begin
  1408.          hs:='';
  1409.          old_parse_types:=parse_types;
  1410.          parse_types:=true;
  1411.          while (token=ID) and
  1412.            (pattern<>'PUBLIC') and
  1413.            (pattern<>'PRIVATE') and
  1414.            (pattern<>'PUBLISHED') and
  1415.            (pattern<>'PROTECTED') do
  1416.            begin
  1417.               sc:=idlist;
  1418.               consume(COLON);
  1419.               p:=read_type('');
  1420.               if do_absolute and (token=ID) and (pattern='ABSOLUTE') then
  1421.                 begin
  1422.                    s:=sc^.get;
  1423.                    if sc^.get<>'' then
  1424.                     Message(parser_e_absolute_only_one_var);
  1425.                    dispose(sc,done);
  1426.                    consume(ID);
  1427.                    if token=ID then
  1428.                      begin
  1429.                         getsym(pattern,true);
  1430.                         consume(ID);
  1431.                         { we should check the result type of srsym }
  1432.                         if not (srsym^.typ in [varsym,typedconstsym]) then
  1433.                          Message(parser_e_absolute_only_to_var_or_const);
  1434.                         abssym:=new(pabsolutesym,init(s,p));
  1435.                         abssym^.typ:=absolutesym;
  1436.                         abssym^.abstyp:=tovar;
  1437.                         abssym^.ref:=srsym;
  1438.                         symtablestack^.insert(abssym);
  1439.                      end
  1440.                    else
  1441.                    if token=CSTRING then
  1442.                      begin
  1443.                         abssym:=new(pabsolutesym,init(s,p));
  1444.                         s:=pattern;
  1445.                         consume(CSTRING);
  1446.                         abssym^.typ:=absolutesym;
  1447.                         abssym^.abstyp:=toasm;
  1448.                         abssym^.asmname:=stringdup(s);
  1449.                         symtablestack^.insert(abssym);
  1450.                      end
  1451.                    else
  1452.                    { absolute address ?!? }
  1453.                    if token=INTCONST then
  1454.                      begin
  1455.                        if (target_info.target=target_GO32V2) then
  1456.                         begin
  1457.                           abssym:=new(pabsolutesym,init(s,p));
  1458.                           abssym^.typ:=absolutesym;
  1459.                           abssym^.abstyp:=toaddr;
  1460.                           abssym^.absseg:=false;
  1461.                           s:=pattern;
  1462.                           consume(INTCONST);
  1463.                           val(s,abssym^.address,code);
  1464.                           if token=COLON then
  1465.                            begin
  1466.                              consume(token);
  1467.                              s:=pattern;
  1468.                              consume(INTCONST);
  1469.                              val(s,l,code);
  1470.                              abssym^.address:=abssym^.address shl 4+l;
  1471.                              abssym^.absseg:=true;
  1472.                            end;
  1473.                           symtablestack^.insert(abssym);
  1474.                         end
  1475.                        else
  1476.                         Message(parser_e_absolute_only_to_var_or_const);
  1477.                      end
  1478.                    else
  1479.                      Message(parser_e_absolute_only_to_var_or_const);
  1480.                 end
  1481.               else
  1482.                 begin
  1483.                    if token=SEMICOLON then
  1484.                      begin
  1485.                         if (symtablestack^.symtabletype=objectsymtable) then
  1486.                           begin
  1487.                              consume(SEMICOLON);
  1488.                              if (token=ID) and (pattern='STATIC') and
  1489.                                 (cs_static_keyword in aktswitches) then
  1490.                                begin
  1491.                                   current_object_option:=current_object_option or sp_static;
  1492.                                   insert_syms(symtablestack,sc,p);
  1493.                                   current_object_option:=current_object_option - sp_static;
  1494.                                   consume(ID);
  1495.                                   consume(SEMICOLON);
  1496.                                end
  1497.                              else
  1498.                                { this will still be a the wrong line !! }
  1499.                                insert_syms(symtablestack,sc,p);
  1500.                           end
  1501.                         else
  1502.                           begin
  1503.                              { at the right line }
  1504.                              insert_syms(symtablestack,sc,p);
  1505.                              consume(SEMICOLON);
  1506.                           end
  1507.                      end
  1508.                    else
  1509.                      begin
  1510.                         insert_syms(symtablestack,sc,p);
  1511.                         if not(is_record) then
  1512.                           consume(SEMICOLON);
  1513.                      end;
  1514.                 end;
  1515.               while token=SEMICOLON do
  1516.                 consume(SEMICOLON);
  1517.            end;
  1518.          if (token=_CASE) and is_record then
  1519.            begin
  1520.               maxsize:=0;
  1521.               consume(_CASE);
  1522.               s:=pattern;
  1523.               getsym(s,false);
  1524.               { may be only a type: }
  1525.               if assigned(srsym) and ((srsym^.typ=typesym) or
  1526.               { and with unit qualifier: }
  1527.                 (srsym^.typ=unitsym)) then
  1528.                 begin
  1529.                    casedef:=read_type('');
  1530.                 end
  1531.               else
  1532.                 begin
  1533.                    consume(ID);
  1534.                    consume(COLON);
  1535.  
  1536.                    casedef:=read_type('');
  1537.                    symtablestack^.insert(new(pvarsym,init(s,casedef)));
  1538.                 end;
  1539.               if not is_ordinal(casedef) then
  1540.                Message(parser_e_ordinal_expected);
  1541.  
  1542.               consume(_OF);
  1543.               startvarrec:=symtablestack^.datasize;
  1544.               repeat
  1545.                 repeat
  1546.                   pt:=expr;
  1547.                   do_firstpass(pt);
  1548.                   if not(pt^.treetype=ordconstn) then
  1549.                     Message(cg_e_illegal_expression);
  1550.                   disposetree(pt);
  1551.                   if token=COMMA then consume(COMMA)
  1552.                     else break;
  1553.                 until false;
  1554.                 consume(COLON);
  1555.                 consume(LKLAMMER);
  1556.                 if token<>RKLAMMER then
  1557.                   read_var_decs(true,false);
  1558.  
  1559.                 { calculates maximal variant size }
  1560.                 maxsize:=max(maxsize,symtablestack^.datasize);
  1561.  
  1562.                 { the items of the next variant are overlayed }
  1563.                 symtablestack^.datasize:=startvarrec;
  1564.                 consume(RKLAMMER);
  1565.                 if token<>SEMICOLON then
  1566.                   break
  1567.                 else
  1568.                   consume(SEMICOLON);
  1569.                 while token=SEMICOLON do
  1570.                   consume(SEMICOLON);
  1571.               until (token=_END) or (token=RKLAMMER);
  1572.  
  1573.               { at last set the record size to that of the biggest variant }
  1574.               symtablestack^.datasize:=maxsize;
  1575.            end;
  1576.          parse_types:=old_parse_types;
  1577.       end;
  1578.  
  1579.     procedure read_declarations(islibrary : boolean);
  1580.  
  1581.       begin
  1582.          repeat
  1583.            case token of
  1584.               _LABEL : label_dec;
  1585.               _CONST : const_dec;
  1586.               _TYPE : type_dec;
  1587.               _VAR : var_dec;
  1588.               _CONSTRUCTOR,_DESTRUCTOR,
  1589.               _FUNCTION,_PROCEDURE,_OPERATOR,_CLASS : unter_dec;
  1590.               _EXPORTS : if islibrary then
  1591.                            read_exports
  1592.                          else
  1593.                            break;
  1594.               else break;
  1595.            end;
  1596.          until false;
  1597.       end;
  1598.  
  1599.     procedure read_interface_declarations;
  1600.  
  1601.       begin
  1602.          {Since the body is now parsed at lexlevel 1, and the declarations
  1603.           must be parsed at the same lexlevel we increase the lexlevel.}
  1604.          inc(lexlevel);
  1605.          repeat
  1606.            case token of
  1607.               _CONST : const_dec;
  1608.               _TYPE : type_dec;
  1609.               _VAR : var_dec;
  1610.               { should we allow operator in interface ? }
  1611.               { of course otherwise you cannot          }
  1612.               { declare an operator usable by other     }
  1613.               { units or progs                       PM }
  1614.               _FUNCTION,_PROCEDURE,_OPERATOR : unter_dec;
  1615.               else
  1616.                  break;
  1617.            end;
  1618.          until false;
  1619.          dec(lexlevel);
  1620.       end;
  1621. end.
  1622. {
  1623.   $Log: pdecl.pas,v $
  1624.   Revision 1.1.1.1.2.2  1998/04/27 23:07:02  peter
  1625.     * small message fixes
  1626.  
  1627.   Revision 1.1.1.1.2.1  1998/04/06 16:21:10  peter
  1628.     * carl and mine bugfixes from the mainbranch applied
  1629.  
  1630.   Revision 1.1.1.1  1998/03/25 11:18:14  root
  1631.   * Restored version
  1632.  
  1633.   Revision 1.31  1998/03/24 21:48:33  florian
  1634.     * just a couple of fixes applied:
  1635.          - problem with fixed16 solved
  1636.          - internalerror 10005 problem fixed
  1637.          - patch for assembler reading
  1638.          - small optimizer fix
  1639.          - mem is now supported
  1640.  
  1641.   Revision 1.30  1998/03/21 23:59:39  florian
  1642.     * indexed properties fixed
  1643.     * ppu i/o of properties fixed
  1644.     * field can be also used for write access
  1645.     * overriding of properties
  1646.  
  1647.   Revision 1.29  1998/03/18 22:50:11  florian
  1648.     + fstp/fld optimization
  1649.     * routines which contains asm aren't longer optimzed
  1650.     * wrong ifdef TEST_FUNCRET corrected
  1651.     * wrong data generation for array[0..n] of char = '01234'; fixed
  1652.     * bug0097 is fixed partial
  1653.     * bug0116 fixed (-Og doesn't use enter of the stack frame is greater than
  1654.       65535)
  1655.  
  1656.   Revision 1.28  1998/03/10 16:27:41  pierre
  1657.     * better line info in stabs debug
  1658.     * symtabletype and lexlevel separated into two fields of tsymtable
  1659.     + ifdef MAKELIB for direct library output, not complete
  1660.     + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  1661.       working
  1662.     + ifdef TESTFUNCRET for setting func result in underfunction, not
  1663.       working
  1664.  
  1665.   Revision 1.27  1998/03/10 01:17:23  peter
  1666.     * all files have the same header
  1667.     * messages are fully implemented, EXTDEBUG uses Comment()
  1668.     + AG... files for the Assembler generation
  1669.  
  1670.   Revision 1.26  1998/03/06 00:52:41  peter
  1671.     * replaced all old messages from errore.msg, only ExtDebug and some
  1672.       Comment() calls are left
  1673.     * fixed options.pas
  1674.  
  1675.   Revision 1.25  1998/03/05 22:43:49  florian
  1676.     * some win32 support stuff added
  1677.  
  1678.   Revision 1.24  1998/03/04 17:33:49  michael
  1679.   + Changed ifdef FPK to ifdef FPC
  1680.  
  1681.   Revision 1.23  1998/03/04 01:35:06  peter
  1682.     * messages for unit-handling and assembler/linker
  1683.     * the compiler compiles without -dGDB, but doesn't work yet
  1684.     + -vh for Hint
  1685.  
  1686.   Revision 1.22  1998/03/02 01:49:00  peter
  1687.     * renamed target_DOS to target_GO32V1
  1688.     + new verbose system, merged old errors and verbose units into one new
  1689.       verbose.pas, so errors.pas is obsolete
  1690.  
  1691.   Revision 1.21  1998/02/28 14:43:47  florian
  1692.     * final implemenation of win32 imports
  1693.     * extended tai_align to allow 8 and 16 byte aligns
  1694.  
  1695.   Revision 1.20  1998/02/19 00:11:07  peter
  1696.     * fixed -g to work again
  1697.     * fixed some typos with the scriptobject
  1698.  
  1699.   Revision 1.19  1998/02/13 10:35:23  daniel
  1700.   * Made Motorola version compilable.
  1701.   * Fixed optimizer
  1702.  
  1703.   Revision 1.18  1998/02/12 17:19:19  florian
  1704.     * fixed to get remake3 work, but needs additional fixes (output, I don't like
  1705.       also that aktswitches isn't a pointer)
  1706.  
  1707.   Revision 1.17  1998/02/12 11:50:25  daniel
  1708.   Yes! Finally! After three retries, my patch!
  1709.  
  1710.   Changes:
  1711.  
  1712.   Complete rewrite of psub.pas.
  1713.   Added support for DLL's.
  1714.   Compiler requires less memory.
  1715.   Platform units for each platform.
  1716.  
  1717.   Revision 1.16  1998/02/11 21:56:36  florian
  1718.     * bugfixes: bug0093, bug0053, bug0088, bug0087, bug0089
  1719.  
  1720.   Revision 1.15  1998/02/06 10:34:25  florian
  1721.     * bug0082 and bug0084 fixed
  1722.  
  1723.   Revision 1.14  1998/02/02 11:56:49  pierre
  1724.     * better line info for var statement
  1725.  
  1726.   Revision 1.13  1998/01/30 21:25:31  carl
  1727.     * bugfix #86 + checking of all other macros for crashes, fixed typeof
  1728.        partly among others.
  1729.  
  1730.   Revision 1.12  1998/01/23 17:12:19  pierre
  1731.     * added some improvements for as and ld :
  1732.       - doserror and dosexitcode treated separately
  1733.       - PATH searched if doserror=2
  1734.     + start of long and ansi string (far from complete)
  1735.       in conditionnal UseLongString and UseAnsiString
  1736.     * options.pas cleaned (some variables shifted to globals)gl
  1737.  
  1738.   Revision 1.11  1998/01/21 21:25:46  florian
  1739.     * small problem with variante records fixed:
  1740.        case a : (x,y,z) of
  1741.        ...
  1742.       is now allowed
  1743.  
  1744.   Revision 1.10  1998/01/13 23:11:13  florian
  1745.     + class methods
  1746.  
  1747.   Revision 1.9  1998/01/12 13:03:31  florian
  1748.     + parsing of class methods implemented
  1749.  
  1750.   Revision 1.8  1998/01/11 10:54:23  florian
  1751.     + generic library support
  1752.  
  1753.   Revision 1.7  1998/01/09 23:08:32  florian
  1754.     + C++/Delphi styled //-comments
  1755.     * some bugs in Delphi object model fixed
  1756.     + override directive
  1757.  
  1758.   Revision 1.6  1998/01/09 18:01:16  florian
  1759.     * VIRTUAL isn't anymore a common keyword
  1760.     + DYNAMIC is equal to VIRTUAL
  1761.  
  1762.   Revision 1.5  1998/01/09 16:08:23  florian
  1763.     * abstract methods call now abstracterrorproc if they are called
  1764.       a class with an abstract method can be create with a class reference else
  1765.       the compiler forbides this
  1766.  
  1767.   Revision 1.4  1998/01/09 13:39:55  florian
  1768.     * public, protected and private aren't anymore key words
  1769.     + published is equal to public
  1770.  
  1771.   Revision 1.3  1998/01/09 13:18:12  florian
  1772.     + "forward" class declarations   (type tclass = class; )
  1773.  
  1774.   Revision 1.2  1998/01/09 09:09:58  michael
  1775.   + Initial implementation, second try
  1776.  
  1777. }
  1778.